C++实现LRU算法
描述
原题:146. LRU 缓存 - 力扣(LeetCode)
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache
类:
LRUCache(int capacity)
以 正整数 作为容量 capacity
初始化 LRU 缓存
int get(int key)
如果关键字 key
存在于缓存中,则返回关键字的值,否则返回 -1
。
void put(int key, int value)
如果关键字 key
已经存在,则变更其数据值 value
;如果不存在,则向缓存中插入该组 key-value
。如果插入操作导致关键字数量超过 capacity
,则应该 逐出 最久未使用的关键字。
函数 get
和 put
必须以 O(1)
的平均时间复杂度运行。
示例
输入
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
1 2 3 4 5 6 7 8 9 10
| LRUCache lRUCache = new LRUCache(2); lRUCache.put(1, 1); lRUCache.put(2, 2); lRUCache.get(1); lRUCache.put(3, 3); lRUCache.get(2); lRUCache.put(4, 4); lRUCache.get(1); lRUCache.get(3); lRUCache.get(4);
|
提示
1 <= capacity <= 3000
0 <= key <= 10000
0 <= value <= 105
- 最多调用
2 * 105
次 get
和 put
核心代码
本题的思想在于要在O(1)时间复杂度上完成 get
和 put
操作。对于 get
则使用哈希表(C++的 std::unordered_map
),对于 put
则使用双链表,同时采用伪头尾指针记录,即可在O(1)时间内完成操作。理解结构图很重要,数据结构图如下:
哈希表
1
| std::unordered_map<int, LinkListNode*> _hashmap;
|
双链表
1 2 3 4 5 6 7 8 9
| typedef struct LinkListNode { int key, value; LinkListNode* prev; LinkListNode* next; LinkListNode():key(0),value(0),prev(nullptr),next(nullptr){}; LinkListNode(int key, int value):key(key),value(value),prev(nullptr),next(nullptr){} }LinkListNode;
|
初始化
1 2 3 4 5 6 7
| LRUCache(int capacity):_capacity(capacity), _size(0) { _dummyHead = new LinkListNode(); _dummyTail = new LinkListNode(); _dummyHead->next = _dummyTail; _dummyTail->prev = _dummyHead; }
|
⭐获取cache
1 2 3 4 5 6 7 8 9 10
| int get(int key) { if(!_hashmap.count(key)) { return -1; } LinkListNode* node = _hashmap[key]; moveToHead(node); return node->value; }
|
⭐加入cahce
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void put(int key, int value) { if(!_hashmap.count(key)) { LinkListNode* node = new LinkListNode(key, value); if(_size >= _capacity){ _hashmap.erase(_dummyTail->prev->key); removeNode(_dummyTail->prev); } else { _size++; } _hashmap[key] = node; addToHead(node); } else { LinkListNode* node = _hashmap[key]; node->value = value; moveToHead(node); } }
|
剩下的 删除指定节点 、移动指定节点到头节点、增加节点到头节点 实现如下
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| typedef struct LinkListNode { int key, value; LinkListNode* prev; LinkListNode* next; LinkListNode():key(0),value(0),prev(nullptr),next(nullptr){}; LinkListNode(int key, int value):key(key),value(value),prev(nullptr),next(nullptr){} }LinkListNode;
class LRUCache { private: int _capacity; int _size; std::unordered_map<int, LinkListNode*> _hashmap; LinkListNode* _dummyHead; LinkListNode* _dummyTail; public: LRUCache(int capacity):_capacity(capacity), _size(0) { _dummyHead = new LinkListNode(); _dummyTail = new LinkListNode(); _dummyHead->next = _dummyTail; _dummyTail->prev = _dummyHead; } int get(int key) { if(!_hashmap.count(key)) { return -1; } LinkListNode* node = _hashmap[key]; moveToHead(node); return node->value; } void put(int key, int value) { if(!_hashmap.count(key)) { LinkListNode* node = new LinkListNode(key, value); if(_size >= _capacity){ _hashmap.erase(_dummyTail->prev->key); removeNode(_dummyTail->prev); } else { _size++; } _hashmap[key] = node; addToHead(node); } else { LinkListNode* node = _hashmap[key]; node->value = value; moveToHead(node); } } void removeNode(LinkListNode* node) { if(node == nullptr) return; node->prev->next = node->next; node->next->prev = node->prev; delete node; } void moveToHead(LinkListNode* node) { if(node == nullptr) return; node->next->prev = node->prev; node->prev->next = node->next;
node->next = _dummyHead->next; node->prev = _dummyHead; _dummyHead->next->prev = node; _dummyHead->next = node; } void addToHead(LinkListNode* node) { if(node == nullptr) return;
node->next = _dummyHead->next; node->prev = _dummyHead; _dummyHead->next->prev = node; _dummyHead->next = node; } };
|
运行结果